#include "Production.h"
#include <cassert>
// Define static members

std::vector<Production> Production::production_vct;
int Production::epsilo_index=Production::insert_production(&epsilo);
bool Production::follow_flag=false;


// Implementation of constructor
Production::Production(int id, std::list<GrammarSymbol*> body_symbols)
    : production_id(id), body_symbol_table(std::move(body_symbols)) {}

// Implementation of get_info method
std::string Production::get_info() {
    std::string str;
    for (auto& elem : body_symbol_table) {
        str += elem->name;
    }
    return str;
}

// Implementation of calculate_first_one method
void Production::calculate_first_one(Production& production) {
    if(production.body_symbol_table.size()==1 && production.body_symbol_table.front()==&epsilo){
        production.first_set.insert(&epsilo);
        return ;
    }
    for (GrammarSymbol* symbol : production.body_symbol_table) {
        if (symbol->type == TERMINAL) {
            production.first_set.insert(static_cast<TerminalSymbol*>(symbol));
            return ;
        } else if (symbol->type == NON_TERMINAL) {

            NonTerminalSymbol* non_termial=(static_cast<NonTerminalSymbol*>(symbol));
            if(non_termial->first_set.size()==0){
                non_termial->calcu_first();
            }
            //这里复制一个副本，因为可能会删掉epsilo，对原来的集合进行修改
            auto symbol_first_set = non_termial->first_set;
     
            bool exist_flag=true;
            if (symbol_first_set.count(&epsilo)) {
                symbol_first_set.erase(&epsilo);
                exist_flag=false;
            }
            production.first_set.insert(symbol_first_set.begin(), symbol_first_set.end());

            if(exist_flag){
                return ;
            }

        }
    }
    production.first_set.insert(&epsilo);
}

void Production::calculate_follow_one(Production& production){
    // assert(production.first_set.size()>=1);

    //对每个表达式右边求follow
    // 获取尾部迭代器
    list<GrammarSymbol*> *symbol_table=&production.body_symbol_table;
    if(symbol_table->size()<=1){
        return;
    }
    auto current = std::prev(symbol_table->end());
    auto current_pre=std::prev(symbol_table->end()); current_pre--;
    while(current!=symbol_table->begin()){
        GrammarSymbol *current_grammar_symbol=*current;
        if((*current_pre)->type==TERMINAL){
            //terminal不需要follow求集合
        }else {
            NonTerminalSymbol *current_pre_grammar_symbol=static_cast<NonTerminalSymbol*>(*current_pre);
            if(current_grammar_symbol->type==TERMINAL){
                current_pre_grammar_symbol->follow_set.insert(static_cast<TerminalSymbol*>(current_grammar_symbol));

            }else{
                set<TerminalSymbol*> temp_set=static_cast<NonTerminalSymbol*>(current_grammar_symbol)->first_set;
                assert(temp_set.size()>0);
                if(temp_set.count(&epsilo)){
                    temp_set.erase(&epsilo);
                }
                current_pre_grammar_symbol->follow_set.insert(temp_set.begin(),temp_set.end());
            }
        }
        current--;
        current_pre--;
    }
    

};

// Implementation of static methods
const std::vector<Production>& Production::get_production_vct() {
    return production_vct;
}

PRO_ID Production::insert_production(std::list<GrammarSymbol*> body_symbols) {
    production_vct.push_back(Production(production_vct.size(), body_symbols));

    return production_vct.size() - 1;
}



void Production::remove_production(int index) {
    assert(index <= 0);
    if (index < production_vct.size()) {
        production_vct.erase(production_vct.begin() + index);
    }
}

PRO_ID Production::get_epsilo_production_id() {
    return epsilo_index;
}

std::string Production::get_info(PRO_ID id) {
    return move(production_vct[id].get_info());
}

void Production::calcu_first(PRO_ID id) {
    assert(id>=0 && id < production_vct.size());
    if(production_vct[id].first_set.size()==0){
        calculate_first_one(production_vct[id]);
    }

}

void Production::calcu_follow(){
    for(int i=1;i<production_vct.size();i++){
        calculate_follow_one(production_vct[i]);
    }
    Production::follow_flag=true;
}

NonTerminalSymbol* Production::get_left_most_nonterminal(PRO_ID id){
    //获取表达式最左边的noterminal
    Production *pro=&production_vct[id];
    GrammarSymbol *grammer_symbol = pro->body_symbol_table.front();
    if(grammer_symbol->type==NON_TERMINAL){
        return static_cast<NonTerminalSymbol *>(grammer_symbol);   
    }else{
        return (NonTerminalSymbol *)nullptr;
    }

};

std::list<GrammarSymbol*> Production::get_production_body_symbol_table(PRO_ID id){
    return production_vct[id].body_symbol_table;
};

std::set<TerminalSymbol *> Production::get_production_first_set(PRO_ID id){
    return production_vct[id].first_set;
};